/*
 * funciones.c
 *
 *  Created on: 11/01/2013
 *      Author: teo
 */
#include "funciones.h"


/************************************************************************
*Función: void inicializar_tablero(char[8][8]);                         *
*Pre: Recibe una matriz de 8 x 8                                        *
*                                                                       *
*Post: Rellena la matriz de espacios                                    *
*                                                                       *
*************************************************************************/

void inicializar_tablero(char tab[8][8]){

	int i,j;

	for(i=0;i<8;i++){

		for(j=0;j<8;j++){

			tab[i][j]=' ';
		}
	}
};

/************************************************************************
*Función: void imprimir_tablero(char[8][8]);                            *
*Pre: Recibe una matriz de 8 x 8                                        *
*                                                                       *
*Post: Muestra la matriz por pantalla                                   *
*                                                                       *
*************************************************************************/

void imprimir_tablero(char tab[8][8]){

	unsigned int i,j;

	system("clear");
	printf("\n          CONECTA-4\n\n");
	printf("+                               +\n");
	for (i=0;i<8;i++){
		for(j=0;j<8;j++){
			printf("| %c ",tab[i][j]);
		}
			printf("|\n");
			printf("|-------------------------------|\n");
	}
	printf("  1   2   3   4   5   6   7   8\n\n");

};

/************************************************************************
*Función: char cambiar_turno(char);                                     *
*Pre: Recibe un char entre X ó O                                        *
*                                                                       *
*Post: Cambia el char segun el que recibe a X si ha recibido un O,      *
*       ó a un O si ha recibido un X                                    *
*************************************************************************/

char cambiar_turno(char tur){

	if (tur=='X')
		return 'O';
	else
		return 'X';

};

/************************************************************************
*Función: bool tablero_lleno(char[8][8]);                               *
*Pre: Recibe una matriz de caracteres de 8x8                            *
*                                                                       *
*Post: Devuelve cierto si cada posición de la fila 0 de la matriz       *
*      es un espacio, en cualquier otro caso, devuelve falso.           *
*************************************************************************/

bool tablero_lleno(char tab[8][8]){

	int x;

	for(x=0;x<8;x++){
		if (tab[0][x]==' '){
			return false;
		}
	}
	return true;
};

/************************************************************************
 *Función: unsigned int pedir_jugada(char tab[8][8], char tur); 	    	*
 *Pre: Recibe un matriz de caracteres ya inicializada, y el turno       *
 *                                                                      *
 *Post: Devuelve un entero sin signo del 0 al 7 que correspondera a la  *
 *      columna de la matriz dada por el usuario.                       *
 *                                                                      *
*************************************************************************/

unsigned int pedir_jugada(char tab[8][8], char tur){

	unsigned int jugada=0;

	printf(" Turno de %c. Inserte la jugada entre 1 y 8: ", tur);
	scanf("%i%*[^\n]",&jugada); //solucionado bug varias jugadas en una

	while(jugada < 1 || jugada > 8 || tab[0][jugada-1]!=' '){

		imprimir_tablero(tab);
		printf("La jugada no es correcta. Por favor, inserte la jugada entre 1 y 8 en una"
				" columna que no esté llena, turno de %c: ", tur);
		scanf("%i",&jugada);

	};
	return jugada-1;
};

/************************************************************************
*Función: void insertar_jugada(char[8][8], int, char);                  *
*Pre: Recibe una matriz de caracteres 8x8, un entero (col),             *
*      y un caracter (tur)                                              *
*Post: Calcula la fila en la que se realiza la jugada, modifica         *
*      la matriz cambiando el valor a turno y devuelve la fila          *
*************************************************************************/

unsigned int insertar_jugada(char tab[8][8], int col, char tur){

	int fila=7;
	while(tab[fila][col]!=' '){
		fila--;
	}
	tab[fila][col]=tur;
	return fila;

};

/************************************************************************
*Función: bool comprobar_jugada(char[8][8],unsigned int);               *
*Pre: Recibe el tablero y el numero de columna                          *
*                                                                       *
*Post: Devuelve true si alguien ha ganado, o false si no.               *
*                                                                       *
*************************************************************************/

bool comprobar_jugada(char tab[8][8], unsigned int col, unsigned int fil){

	return (comprobar_horizontal(tab, col, fil)||comprobar_vertical(tab, col, fil)
			||comprobar_diagonal1(tab, col, fil)||comprobar_diagonal2(tab, col, fil));

};

/************************************************************************
*Función: bool comprobar_vertical(char[8][8],unsigned int);             *
*Pre: Pasarle el tablero y la columna que hay que comprobar.            *
*                                                                       *
*Post: Devuelve 0 si no hay fichas suficientes por debajo de la ficha   *
*      mas alta de la columna, devuelve 0/1 si las tres fichas          *
*      inferiores a la mas alta son iguales a esta ultima.              *
*************************************************************************/

bool comprobar_vertical( char tablero[8][8], unsigned int columna, unsigned int fila ){
  
  return (comprobar_adyacentes(tablero,columna,fila,0,1)>=3) ? true : false;
 
//devuelve la comparacion de la ficha nueva con las 3 que tiene por debajo
};

/************************************************************************
*Función: comprobar_adyacentes(char[8][8],unsigned int,unsigned int,    *
*         int,int);                                                     *
*Pre: recibe el tablero, la posicion de la fiche, el desplazamiento     *
*     horizontal(dh) y desplazamiento vertical(dv)                      *
*Post: devuelve un entero con el numero de fichas adyacentes iguales    *
*      a la posicion origen[f][c]                                       *
*************************************************************************/

int comprobar_adyacentes(char tablero[8][8], unsigned int c,
						   unsigned int f, int dh, int dv ){ //dh y dv desplazamiento horizontal/vertical

	int contador=0;
	int colu=c+dh; //seleccionamos la adyacente
	int fila=f+dv;
		while ((colu >= 0 && colu <=7) && (fila >=0 && fila <=7) &&
				(tablero[fila][colu] == tablero[f][c]) ){
			contador++;
			 colu+=dh; //movemos la columna
			 fila+=dv; //movemos la fila
		}
	return contador;

};

/************************************************************************
*Función: comprobar_horizontal(char[8][8],unsigned int,unsigned int);   *
*Pre: recibe una matriz 8 x 8(tab) y un entero sin signo (columna)      *
*                                                                       *
*Post: devuelve true si hay 4 fichas iguales horizontalmente y          *
*      false en caso contrario.                                         *
*************************************************************************/

bool comprobar_horizontal(char tablero[8][8], unsigned int columna,
							 unsigned int fila){

	int control;

	control = comprobar_adyacentes(tablero,columna,fila,-1,0)+ 	//izda
			  comprobar_adyacentes(tablero,columna,fila,1,0);	//dcha
           
  return (control >= 3) ? true : false;
};

/************************************************************************
*Función: bool comprobar_diagonal1(char[8][8],unsigned int unsigned int)*
*Pre: recibe una matriz 8 x 8(tab) y un entero sin signo (columna)      *
*                                                                       *
*Post: devuelve true si hay 4 fichas iguales horizontalmente y          *
*      false en caso contrario.                                         *
*************************************************************************/

bool comprobar_diagonal1(char tablero[8][8],
						    unsigned int columna, unsigned int fila){

	int control;

	control = comprobar_adyacentes(tablero,columna,fila,-1,-1)+ //izda -- arriba
			  comprobar_adyacentes(tablero,columna,fila,1,1);	//dcha -- abajo

  return (control >= 3) ? true : false;

};

/************************************************************************
*Función: bool comprobar_diagonal2(char[8][8],unsigned int unsigned int)*
*Pre: recibe una matriz 8 x 8(tab) y un entero sin signo (columna)      *
*                                                                       *
*Post: devuelve true si hay 4 fichas iguales horizontalmente y          *
*      false en caso contrario.                                         *
*************************************************************************/

bool comprobar_diagonal2(char tablero[8][8],
							unsigned int columna, unsigned int fila){

	int control;

	control = comprobar_adyacentes(tablero,columna,fila,-1,1)+	//izda -- abajo
			  comprobar_adyacentes(tablero,columna,fila,1,-1);	//dcha --arriba

  return (control >= 3) ? true : false;
};

//Precondición: vacía
//Postcondición: imprime un menu numérico con las herramientas del programa:
					//1.-Juego dos jugadores en el mismo ordenador
					//2.-Comenzar una partida en la red.
					//3.-Unirse a una partida en red.
					//4.-Generación de pruebas.
					//Devuelve la opción introducida, siempre que esté dentro del menú.

unsigned int imprimir_menu(){

	int numero;

		printf("Elige una de las opciones\n");
		printf("1.-Juego dos jugadores en el mismo ordenador\n");
		printf("2.-Comenzar una partida en la red\n");
		printf("3.-Unirse a una partida en red\n");
		printf("4.-Generación de pruebas\n");

		scanf("%i", &numero);

	//TODO: GRUPO 2: IMPLEMENTAR imprimir_menu()

	return numero;
};


//Precondición: n es un número natural con el número de ficheros de prueba creados.
//Postcondición: crea n ficheros con un "1" seguido 64 enteros entre 1 y 8 uno en cada línea.
//el "1" indica que tomaremos la opción 1 del menú.


void crear_ficheros_prueba(int n){
int contador=0,i;
FILE *prueba;
char nombre[15];
srand( time(NULL) );
 while(contador<n) {
   contador++;
   sprintf(nombre,"%i.txt",contador);
   prueba=fopen(nombre,"w+");
   fprintf(prueba,"1\n");
   for(i=0;i<64;i++) {
       fprintf(prueba,"%i\n",rand()%8+1);
   }
   fclose(prueba);
 }
};

void partida_local(){

  //Precondición: juega partida en modo local
  //Postcondición: vacía


	char tablero[8][8];
    char turno='X';
    inicializar_tablero(tablero);
    bool ganador=false;
    unsigned int columna, fila;


    while(!ganador && !tablero_lleno(tablero)){

    	turno=cambiar_turno(turno);

    	imprimir_tablero(tablero);

        columna=pedir_jugada(tablero, turno);

        fila=insertar_jugada(tablero,columna,turno);

        ganador=comprobar_jugada(tablero,columna,fila);

    }

        imprimir_tablero(tablero);

        if( ganador )
                printf("El ganador es el jugador %c\n\n",turno);
        else
                printf("Se ha llenado el tablero sin un ganador, el resultado es EMPATE\n\n");

};

void comenzar_partida_red(){

  char tablero[8][8];
  char turno='O';
  inicializar_tablero(tablero);
  bool ganador=false;
  char partida[25]="partida_";
  unsigned int columna, fila;
  int sock;

  sock=iniciar_comunicacion();
  crear_nombre_fichero(partida);

  while(!ganador && !tablero_lleno(tablero) ){

    columna=recibir_jugada(sock);

    turno=cambiar_turno(turno);

    fila=insertar_jugada(tablero,columna,turno);
    guardar_en_fichero(partida,columna);

    imprimir_tablero(tablero);

    ganador=comprobar_jugada( tablero, columna, fila );

    if( !ganador ){

      turno=cambiar_turno(turno);

      columna=pedir_jugada(tablero, turno);

      fila=insertar_jugada(tablero,columna,turno);

      imprimir_tablero(tablero);

      enviar_jugada(sock, columna);
      guardar_en_fichero(partida,columna);

      ganador=comprobar_jugada(tablero,columna,fila);

    }

  }

  close(sock);

  imprimir_tablero(tablero);

 if( ganador )
    printf("El ganador es el jugador %c\n",turno);
  else
    printf("Se ha llenado el tablero sin un ganador, el resultado es EMPATE\n");

}

void unirse_a_partida_red(){

  char tablero[8][8];
  char turno='O';
  inicializar_tablero(tablero);
  bool ganador=false;
  char partida[25]="partida_";
  unsigned int columna, fila;
  int sock;

  crear_nombre_fichero(partida);

  sock=conectar_con_servidor();

  while(!ganador && !tablero_lleno(tablero) ){

      turno=cambiar_turno(turno);

      imprimir_tablero(tablero);

      columna=pedir_jugada(tablero, turno);

      fila=insertar_jugada(tablero,columna,turno);

      enviar_jugada(sock, columna);
      guardar_en_fichero(partida,columna);

      ganador=comprobar_jugada(tablero,columna,fila);


      if( !ganador ){
    	  imprimir_tablero(tablero);

    	  columna=recibir_jugada(sock);

    	  turno=cambiar_turno(turno);

    	  fila=insertar_jugada(tablero,columna,turno);
    	  guardar_en_fichero(partida,columna);

    	  ganador=comprobar_jugada( tablero, columna, fila );
  	  }

  }

  close(sock);

  imprimir_tablero(tablero);

  if( ganador )
    printf("El ganador es el jugador %c\n",turno);
  else
    printf("Se ha llenado el tablero sin un ganador, el resultado es EMPATE\n");

};

void crear_nombre_fichero(char fichero[25]){

	time_t tiempo=time(NULL);
	char temporal[20];
	sprintf(temporal,"%ld",tiempo);
	strcat(fichero,temporal);

};

void guardar_en_fichero(char partida[25],unsigned int columna){

	FILE* fichero=fopen(partida, "a");
	fprintf(fichero,"%i\n",columna+1); //movimiento usuario del 1 al 8
	fclose(fichero);


}


